package com.agile.leetcode.jvm.outofheapmemory;

import org.apache.commons.codec.Charsets;
import org.caffinitas.ohc.CacheSerializer;
import org.caffinitas.ohc.OHCache;
import org.caffinitas.ohc.OHCacheBuilder;

import java.nio.ByteBuffer;

/**
 * OHCache 这个东西，和 Map 差不多，基本方法也是 put，get。
 * 只是 put 的对象，也就是缓存的对象，是由用户自定义的序列化方法决定的。比如我上面这个只能缓存字符串类型，如果你想要放个自定义对象进去，就得实现一个自定义对象的系列化方法，很简单的，网上搜一下，多的很。
 *
 * @Author:ChenZhangKun
 * @Date: 2023/2/6 20:58
 */
public class Demo {

    public static void main(String[] args) {
        OHCache ohCache = OHCacheBuilder.<String, String>newBuilder()
                // key的序列化方式
                .keySerializer(Demo.cacheSerializer)
                // value的序列化方式
                .valueSerializer(Demo.cacheSerializer)
                // 定义2G
                .capacity(1027*1024*2)

                .build();
        ohCache.put("czk", "cz;");
        System.out.println(ohCache.get("czk"));
    }

    public static final CacheSerializer<String> cacheSerializer = new CacheSerializer<String>() {
        @Override
        public void serialize(String s, ByteBuffer byteBuffer) {
            byte[] bytes = s.getBytes(Charsets.UTF_8);
            // 用前16位记录数组长度
            byteBuffer.put((byte) ((bytes.length >>> 8) & 0xFF));
            byteBuffer.put((byte) ((bytes.length) & 0xFF));
            byteBuffer.put(bytes);
        }

        @Override
        public String deserialize(ByteBuffer buf) {
            int length = (((buf.get() & 0xff) << 8) + ((buf.get() & 0xff)));
            byte[] bytes = new byte[length];
            buf.get(bytes);

            return new String(bytes, Charsets.UTF_8);
        }

        @Override
        public int serializedSize(String s) {
            byte[] bytes = s.getBytes(Charsets.UTF_8);
            if (bytes.length > 65535) {
                throw new RuntimeException("encoded string too long: " + bytes.length + " bytes");
            }
            return bytes.length + 2;
        }
    };

}
